package components

import (
	"encoding/json/v2"
	"fmt"
	"strings"
)

// A collection of dictionary entries for a word in different languages.
type EntriesByLanguageAndWord struct {
	// The word being looked up.
	Word string `json:"word"`
	// All dictionary entries for this word in different languages and contexts.
	Entries []Entry `json:"entries"`
	// Information about where this data comes from and how it can be used.
	Source Source `json:"source"`
}

// A dictionary entry for a word in one specific language.
type Entry struct {
	// Which language this entry is for.
	Language       Language        `json:"language"`
	PartOfSpeech   string          `json:"partOfSpeech"`
	Pronunciations []Pronunciation `json:"pronunciations"`
	Forms          []Form          `json:"forms"`
	Senses         []Sense         `json:"senses"`
	Synonyms       []string        `json:"synonyms"`
	Antonyms       []string        `json:"antonyms"`
}

// A different form of the word (like plural, past tense, etc.).
type Form struct {
	// The different form of this word.
	Word string `json:"word"`
	// Labels describing what kind of form this is (plural, past tense, etc.).
	Tags []string `json:"tags"`
}

// Information about a language.
type Language struct {
	// ISO 639-1/639-3 (2 or 3 letter) language code.
	Code string `json:"code"`
	// The full name of this language in English.
	Name string `json:"name"`
}

// Legal terms for using the dictionary data.
type License struct {
	// Name of the license.
	Name string `json:"name"`
	// Link to read the full license terms.
	Url string `json:"url"`
}

// How to pronounce a word using phonetic symbols.
type Pronunciation struct {
	// The type of pronunciation (like "ipa", "enpr", etc.).
	Type PronunciationType `json:"type"`
	// The pronunciation written in the specified notation.
	Text string `json:"text"`
	// Labels describing this pronunciation (like dialect or formality level).
	Tags []string `json:"tags"`
}

// The type of pronunciation (like "ipa", "enpr", etc.).
type PronunciationType string

const (
	IPA  PronunciationType = "ipa"
	ENPR PronunciationType = "enpr"
)

func (p PronunciationType) String() string {
	return string(p)
}

func (p PronunciationType) MarshalJSON() ([]byte, error) {
	return json.Marshal(p.String())
}

func (p *PronunciationType) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}

	switch strings.ToLower(s) {
	case "ipa":
		*p = IPA
	case "enpr":
		*p = ENPR
	default:
		return fmt.Errorf("unknown pronunciation type: %s", s)
	}
	return nil
}

// A quote from a book or other source showing how the word is used.
type Quote struct {
	// The actual quote text.
	Text string `json:"text"`
	// Where this quote came from (book title, author, etc.).
	Reference string `json:"reference"`
}

// One specific meaning of a word with examples and related information.
type Sense struct {
	// What this meaning of the word means.
	Definition string `json:"definition"`
	// Labels about how this meaning is used (formal, old-fashioned, technical, etc.).
	Tags []string `json:"tags"`
	// Example sentences showing how to use this meaning.
	Examples []string `json:"examples"`
	// Real quotes from books or other sources using this word.
	Quotes []Quote `json:"quotes"`
	// Words that mean the same as this specific meaning.
	Synonyms []string `json:"synonyms"`
	// Words that mean the opposite of this specific meaning.
	Antonyms []string `json:"antonyms"`
	// How to say this meaning in other languages.
	Translations []Translation `json:"translations"`
	// More specific meanings within this meaning.
	Subsenses []Sense `json:"subsenses"`
}

// Information about where the dictionary data comes from.
type Source struct {
	// Link to the original Wiktionary page.
	Url string `json:"url"`
	// Legal information about how you can use this data.
	License License `json:"license"`
}

// How to say a word in another language.
type Translation struct {
	// Which language this translation is in.
	Language Language `json:"language"`
	// The word or phrase in that language.
	Word string `json:"word"`
}
